/** * ChainedException - Exception which contains source exception. * * Copyright (c) 2000, 2001, 2002 * Marty Phelan, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ // Based partly on example by Barry Mosher in Java Developers Journal (March 2000) package com.taursys.util; import java.io.PrintStream; import java.io.PrintWriter; /** * A ChainedException is a subclass of Exception which contains a Throwable cause. * This allows for the creation of a single linked list of exceptions and their * respective causes. The printStackTrace() methods display the trace for this * exception and then invoke the method for the cause (which can in turn invoke * a trace for its ancestory). * <p> * The ChainedException also provides for diagnostic information. This * information will be displayed in the stack trace, but not included in the * basic message. The diagnostic information is available through the * getLocalizedMessage method. */ public class ChainedException extends Exception { public static final int REASON_INVALID_REASON_CODE = 0; public static final int REASON_UNSPECIFIED = 1; private static final String[] messages = new String[] { "Invalid reason code.", "Unspecified reason", }; protected Throwable cause; protected String diagnosticInfo; protected int reason = REASON_UNSPECIFIED; protected String userFriendlyMessage = "A system exception has occurred"; // ************************************************************************ // Static Class Methods // ************************************************************************ /** * Returns String for given reason code else String for REASON_INVALID_REASON_CODE. */ public static String getReasonMessage(int reason) { if (reason >= 0 && reason < messages.length) return messages[reason]; else return messages[REASON_INVALID_REASON_CODE]; } /** * Returns String for given reason code else String for REASON_INVALID_REASON_CODE. */ public static String getInvalidMessage() { return messages[REASON_INVALID_REASON_CODE]; } // ************************************************************************ // Public Constructors // ************************************************************************ /** * Creates a ModelException with a reason code. * The reason code will also be used to set the message. */ public ChainedException(int reason) { super(getReasonMessage(reason)); this.reason = reason; } /** * Creates a ModelException with a reason code and cause. * The reason code will also be used to set the message. */ public ChainedException(int reason, Throwable cause) { super(getReasonMessage(reason)+": "+cause.getMessage()); this.reason = reason; this.cause = cause; } /** * Creates a ModelException with a reason code, cause and diagnostic information. * The reason code will also be used to set the message. */ public ChainedException(int reason, Throwable cause, String diagnosticInfo) { this(reason, cause); this.diagnosticInfo = diagnosticInfo; } /** * Creates a ModelException with a reason code and diagnostic information. * The reason code will also be used to set the message. */ public ChainedException(int reason, String diagnosticInfo) { this(reason); this.diagnosticInfo = diagnosticInfo; } // ************************************************************************ // Protected Constructors // ************************************************************************ /** * Creates a ChainedException with a message. * This constructor is only available to subclasses. */ protected ChainedException(String message) { super(message); } /** * Creates a ChainedException with a message. * This constructor is only available to subclasses. * This constructor does not alter the message. It simply stores the * message and reason. */ protected ChainedException(String message, int reason) { super(message); this.reason = reason; } /** * Creates a ChainedException with a message. * This constructor is only available to subclasses. * This constructor appends the cause message to given message separated * by a ": ". It then stores the message, reason code and cause. */ protected ChainedException(String message, int reason, Throwable cause) { this(message + ": " + cause.getMessage(), reason); this.cause = cause; } // ************************************************************************ // Property Accessors // ************************************************************************ /** * Returns the reason code. */ public int getReason() { return reason; } /** * Accesses the original cause of this ChainedException. */ public Throwable getCause() { return cause; } /** * Returns the current userFriendlyMessage. */ public String getUserFriendlyMessage() { return userFriendlyMessage; } /** * Override of superclass method to provide diagnostic information (if exists). * Provides original message plus diagnostic information. */ public String getLocalizedMessage() { if (diagnosticInfo != null && diagnosticInfo.length() > 0) return getMessage() + "\n" + diagnosticInfo; else return getMessage(); } /** * Returns the current diagnostic information. */ public String getDiagnosticInfo() { return diagnosticInfo; } // ************************************************************************ // Display Methods // ************************************************************************ /** * Prints this ChainedException and its cause to the standard error stream. */ public void printStackTrace() { super.printStackTrace(); if (cause != null) { cause.printStackTrace(); } } /** * Prints this ChainedException and its cause to the given print stream. */ public void printStackTrace(PrintStream printStream) { super.printStackTrace(printStream); if (cause != null) { cause.printStackTrace(printStream); } } /** * Prints this ChainedException and its cause to the given print writer. */ public void printStackTrace(PrintWriter printWriter) { super.printStackTrace(printWriter); if (cause != null) { cause.printStackTrace(printWriter); } } // ************************************************************************ // Testing/Designing Methods // ************************************************************************ /** * Main for designing/viewing */ static public void main(String[] args) { try { throw new ChainedException(1, new Exception("Cause message"),"Trace x=1, y=2"); } catch (Exception ex) { System.out.println("Exception toString:\n===========\n"+ex); System.out.println("=========================================================="); System.out.println("Exception Message:\n===========\n"+ex.getMessage()); System.out.println("=========================================================="); System.out.println("Exception Localized Message:\n=================\n"+ex.getLocalizedMessage()); System.out.println("=========================================================="); System.out.println("Stack Trace:"); System.out.println("=========================================================="); ex.printStackTrace(); } } }